// 语音播报的服务端实现
// 主要功能是接收来自客户端的语音播报请求，并使用espeak朗读文本
// 使用回调函数的方式处理音频事件，可以根据需要进行修改
// jette 2025.7.31
#include "xunjian_robot/speaker.hpp"
#include <rclcpp/rclcpp.hpp>

Speaker::Speaker(const std::string& node_name) 
    : Node(node_name)
{
    // 初始化espeak
    int result = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, nullptr, espeakINITIALIZE_PHONEME_EVENTS);
    if (result == -1) {
        RCLCPP_ERROR(this->get_logger(), "Failed to initialize espeak");
        throw std::runtime_error("Failed to initialize espeak");
    }
    
    // 设置语音参数
    espeak_SetParameter(espeakRATE, 130, 0);    // 语速
    espeak_SetParameter(espeakVOLUME, 150, 0);  // 音量
    espeak_SetParameter(espeakPITCH, 100, 0);    // 音调

    
    // 设置中文语音
    const char* voice_name = "zh-CN";  // "Mandarin"putongguo, "zh-CN"
    // const char* voice_names[] = {
    // "Mandarin",      // 普通话
    // "zh-CN",         // 简体中文
    // "zh",            // 中文
    // "Chinese",       // 中文
    // nullptr
    // };
    espeak_VOICE voice_selector = {};
    memset(&voice_selector, 0, sizeof(espeak_VOICE));
    voice_selector.languages = voice_name;
    espeak_SetVoiceByProperties(&voice_selector);
    
    // 创建服务
    speech_service_ = this->create_service<SpeechText>(
        "speech_text",
        std::bind(&Speaker::speak_text_callback, this, std::placeholders::_1, std::placeholders::_2));
    
    RCLCPP_INFO(this->get_logger(), "语音播报服务已上线");
}

Speaker::~Speaker()
{
    espeak_Terminate();
}

void Speaker::speak_text_callback(
    const std::shared_ptr<SpeechText::Request> request,
    const std::shared_ptr<SpeechText::Response> response)
{
    // RCLCPP_INFO(this->get_logger(), "正在朗读: %s", request->text.c_str());
    
    // 使用espeak朗读文本
    espeak_Synth(request->text.c_str(), request->text.length(), 0, POS_CHARACTER, 0,
                 espeakCHARS_AUTO, nullptr, nullptr);
    
    // 等待朗读完成
    espeak_Synchronize();
    
    response->result = true;
    // RCLCPP_INFO(this->get_logger(), "朗读完成");
}

int Speaker::espeak_callback(short* wav, int numsamples, espeak_EVENT* events)
{
    // 这里可以处理音频回调事件
    // 标记参数预防警告
    (void)wav;
    (void)numsamples;
    (void)events;
    return 0;
}

// 主函数
int main(int argc, char* argv[])
{
    rclcpp::init(argc, argv);
    auto node = std::make_shared<Speaker>("speaker");
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}